package com.stox.core.manager;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.stox.core.dao.ExchangeDao;
import com.stox.core.event.ApplicationEventPublisher;
import com.stox.core.event.ExchangeAddedEvent;
import com.stox.core.event.ExchangeConfiguredEvent;
import com.stox.core.model.Exchange;
import com.stox.core.model.exception.StoxException;
import com.stox.design.AfterUiInitializable;
import com.stox.ioc.Container;

public class ExchangeManager implements AfterUiInitializable<Void,Void>{

	private ExchangeDao exchangeDao;
	private Map<String, Exchange> exchangeMap;
	
	public ExchangeManager() {
		this.exchangeMap = new HashMap<String, Exchange>();
		this.exchangeDao = Container.get(ExchangeDao.class);
	}
	
	@Override
	public int getOrder() {
		return 0;
	}
	
	@Override
	public boolean isInitialized() {
		return exchangeMap != null && !exchangeMap.isEmpty();
	}
	
	@Override
	public Void invoke(Void payload) {
		try {
			List<Exchange> exchanges = exchangeDao.get();
			for(Exchange exchange : exchanges){
				exchangeMap.put(exchange.getCode(), exchange);
				ApplicationEventPublisher.publish(new ExchangeAddedEvent(exchange));
			}
		} catch (SQLException e) {
			throw new StoxException(e);
		}
		return null;
	}
	
	public void configureExchanges(List<Exchange> exchanges){
		for(Exchange exchange : exchangeMap.values()){
			try {
				boolean active = exchanges.contains(exchange);
				exchangeDao.updateConfigured(exchange.getCode(), active);
				if(!exchange.isConfigured() && active){
					ApplicationEventPublisher.publish(new ExchangeConfiguredEvent(exchange));
				}
				exchange.setConfigured(active);
			} catch (SQLException e) {
				throw new StoxException(e);
			}
		}
	}
	
	public List<Exchange> getConfiguredExchanges(){
		List<Exchange> exchanges = new ArrayList<Exchange>();
		for(Exchange exchange : exchangeMap.values()){
			if(exchange.isConfigured()){
				exchanges.add(exchange);
			}
		}
		return exchanges;
	}
	
	public void firstTimeDownloadCompleted(String exchangeCode){
		try{
			exchangeDao.updateFirstTimeDownloadCompleted(exchangeCode, true);
		} catch (SQLException e) {
			throw new StoxException(e);
		}
	}
	
	public Exchange findByCode(String code){
		return exchangeMap.get(code);
	}
	
	public Exchange findByName(String name){
		for(Exchange exchange : exchangeMap.values()){
			if(exchange.getName().equalsIgnoreCase(name)){
				return exchange;
			}
		}
		return null;
	}
	
	public List<Exchange> findAll(){
		List<Exchange> exchanges = new ArrayList<Exchange>(exchangeMap.values());
		Collections.sort(exchanges);
		return exchanges;
	}
	
	public void updateLastTradingDate(String code, Date date){
		try {
			exchangeDao.updateLastTradingDate(code, date);
			Exchange exchange = findByCode(code);
			if(exchange != null){
				exchange.setLastTradingDate(date);
			}
		} catch (SQLException e) {
			throw new StoxException(e);
		}
	}
	
	public void persist(Exchange exchange){
		try {
			exchange.format();
			exchangeDao.persist(exchange);
			exchangeMap.put(exchange.getCode(), exchange);
			ApplicationEventPublisher.publish(new ExchangeAddedEvent(exchange));
		} catch (SQLException e) {
			throw new StoxException(e);
		}
	}
}
